﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace Mimoza.Transport
{

    class AdaptersInfo
    {
#if WindowsCE
        const CharSet DefaultChartSet = CharSet.Auto;
#else
        const CharSet DefaultChartSet = CharSet.Ansi;
#endif

        public static List<Adapter> GetAdapters()
        {
            int size = 0;
            // this chunk of code teases out the first adapter info
            IntPtr empty = IntPtr.Zero;
            int r = GetAdaptersInfo(empty, ref size);
            if ((r != IPConfigConst.ERROR_SUCCESS) && (r != IPConfigConst.ERROR_BUFFER_OVERFLOW))
            {
                return null;
            }
            //Byte[] buffer = new Byte[size];
            IntPtr buffer = Marshal.AllocHGlobal(size);
            r = GetAdaptersInfo(buffer, ref size);
            if (r != IPConfigConst.ERROR_SUCCESS)
            {
                return null;
            }

            AdapterInfo Adapter = new AdapterInfo();
            Adapter = (AdapterInfo)Marshal.PtrToStructure(buffer, typeof(AdapterInfo));

            List<Adapter> addresses = new List<Adapter>();
            do
            {
                addresses.Add( new Adapter( new MacAddress(Adapter.Address),
                    ConvertToString(Adapter.IPAddressList.IPAddressString),
                    ConvertToString(Adapter.AdapterName)));
                IntPtr p = Adapter.NextPointer;
                if (p != IntPtr.Zero)
                {
                    Adapter = (AdapterInfo)Marshal.PtrToStructure(p, typeof(AdapterInfo));
                }
                else
                {
                    break;
                }
            } 
            while (true);

            return addresses;
        }


        private class IPConfigConst
        {
            public const int MAX_ADAPTER_DESCRIPTION_LENGTH = 128;
            public const int MAX_ADAPTER_NAME_LENGTH = 256;
            public const int MAX_ADAPTER_ADDRESS_LENGTH = 8;
            public const int ERROR_BUFFER_OVERFLOW = 111;
            public const int ERROR_SUCCESS = 0;
        }

#if WindowsCE
        static string ConvertToString(Byte[] array)
        {
            string result = "";
            for (int i = 0; i < array.Length && array[i] != 0; i++)
            {
                result += (char)array[i];
            }
            return result;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = DefaultChartSet)]
        private struct IPAddrString
        {
            public IntPtr NextPointer;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4 * 4)]
            public Byte[] IPAddressString;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4 * 4)]
            public Byte[] IPMaskString;
            public int Context;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = DefaultChartSet)]
        private struct AdapterInfo
        {
            public IntPtr NextPointer;
            public int ComboIndex;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = IPConfigConst.MAX_ADAPTER_NAME_LENGTH + 4)]
            public Byte[] AdapterName;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = IPConfigConst.MAX_ADAPTER_DESCRIPTION_LENGTH + 4)]
            public Byte[] Description;
            public int AddressLength;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = IPConfigConst.MAX_ADAPTER_ADDRESS_LENGTH)]
            public Byte[] Address;
            public int Index;
            public int Type;
            public int DhcpEnabled;
            public IntPtr CurrentIPAddress;
            public IPAddrString IPAddressList;
            public IPAddrString GatewayList;
            public IPAddrString DhcpServer;
            public Boolean HaveWins;
            public IPAddrString PrimaryWinsServer;
            public IPAddrString SecondaryWinsServer;
            public int LeaseObtained;
            public int LeaseExpires;
        }
#else
        static string ConvertToString(string str)
        {
            return str;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = DefaultChartSet)]
        private struct IPAddrString
        {
            public IntPtr NextPointer;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4 * 4)]
            public String IPAddressString;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4 * 4)]
            public String IPMaskString;
            public int Context;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = DefaultChartSet)]
        private struct AdapterInfo
        {
            public IntPtr NextPointer;
            public int ComboIndex;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = IPConfigConst.MAX_ADAPTER_NAME_LENGTH + 4)]
            public string AdapterName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = IPConfigConst.MAX_ADAPTER_DESCRIPTION_LENGTH + 4)]
            public string Description;
            public int AddressLength;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = IPConfigConst.MAX_ADAPTER_ADDRESS_LENGTH)]
            public Byte[] Address;
            public int Index;
            public int Type;
            public int DhcpEnabled;
            public IntPtr CurrentIPAddress;
            public IPAddrString IPAddressList;
            public IPAddrString GatewayList;
            public IPAddrString DhcpServer;
            public Boolean HaveWins;
            public IPAddrString PrimaryWinsServer;
            public IPAddrString SecondaryWinsServer;
            public int LeaseObtained;
            public int LeaseExpires;
        }
#endif

        [DllImport("Iphlpapi.dll", CharSet = DefaultChartSet)]
        private static extern int GetAdaptersInfo(IntPtr PAdapterInfoBuffer, ref int size);
    }
}
